package jpave.query_interface;
/**********************************************************
 *  XXX Basic Prompt Panel
 * 	XXX Column Select Panel
 *  XXX Anno Select Panel
 *  XXX Column data
 */
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Collections;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import jpave.manager.ManagerFrame;
import util.Debug.ErrorReport;

public class BasicPromptPanel extends JPanel {
	private static final long serialVersionUID = 6371517539623729378L;
	
	private static final int NGENERAL = 4; // number of General columns to check on

	public static final int VIEW_MODE_INDIVIDUAL_HIT = 0; 
	public static final int VIEW_MODE_INDIVIDUAL_CONTIG = 1; 
	public static final int VIEW_MODE_GROUP_HIT = 2; 
	public static final int VIEW_MODE_GROUP_CONTIG = 3; 
	
	public static final int QUERY_MODE_HIT_ID = 0;
	public static final int QUERY_MODE_HIT_DESCRIPTION = 1;
	public static final int QUERY_MODE_CONTIG_NAME = 2;
	public static final int QUERY_MODE_CONTIG_NOTE = 3;
	public static final int QUERY_MODE_CONTIG_READ = 4;
	
	public static final int COLUMN_SELECT_WIDTH = 200;
	public static final int COLUMN_LEFT_MARGIN = 50;
	
	private static final int ANNODB_NUM_COLUMNS = 4;
	private static final int ANNODB_COLUMN_WIDTH = 150;
	
	private static final int MAIN_PANEL_LABEL_WIDTH = 100;
	
	private static final int DEFAULT_PROMPT_SIZE = 20;
	private static final int DEFAULT_RESULT_LIMIT = 1000;
	private static final int DEFAULT_RANK_LIMIT = 100;  // CAS 4/30/13
	private static final double DEFAULT_EVAL_LIMIT = 1e-3;
	
	private static final String QUERY_MODE_HIT_ID_LABEL = "Hit IDs";
	private static final String QUERY_MODE_HIT_DESCRIPTION_LABEL = "Descriptions";
	private static final String QUERY_MODE_CONTIG_NAME_LABEL = "Seq ID";
	private static final String QUERY_MODE_CONTIG_NOTE_LABEL = "Remarks";
	private static final String QUERY_MODE_CONTIG_READ_LABEL = "Read Names";
	
	private static final String [] HIT_QUERY_MODES = { 
		QUERY_MODE_HIT_ID_LABEL, QUERY_MODE_HIT_DESCRIPTION_LABEL };
	private static final String [] CONTIG_QUERY_MODES = { 
		QUERY_MODE_CONTIG_NAME_LABEL, QUERY_MODE_CONTIG_NOTE_LABEL, QUERY_MODE_CONTIG_READ_LABEL };
	
	// If change order here, change in JPaveDBWrapper (check for all places)
	// and in BestQueryResultsListPanel (again, check for all places)
	// CAS 1-may-13 change order of columns
	private static final String [] INDIVIDUAL_HIT_COLUMN_STATIC_NAMES = { 	
		"Row", "Seq ID", "Hit ID", "Eval",  "Description", "Species", 
		"Type", "Taxonomy", "Rank", "Align Len","Hit Start", "Hit End", "Seq Start", "Seq End"};
	private static final String [] GROUP_HIT_COLUMN_STATIC_NAMES = { 
		"Row", "Hit ID", "# Seqs", "Description", "Species", "Type", "Taxonomy"}; 
	
	private static final String [] INDIVIDUAL_CONTIG_COLUMN_STATIC_NAMES  = 
		{ "Row", "Seq ID", "Read", "Buried" };
	// CAS 1-may-13 change order of columns
	private static final String [] GROUP_CONTIG_COLUMN_STATIC_NAMES_DISPLAY   = 
		{ "Row", "Seq ID", "Best DB Hit", "Best DB Hit Description", "Remark", "TotalRead"};
	private static final Color BGCOLOR = ManagerFrame.BGCOLOR;
	
	// XXX Basic Prompt Panel
	public BasicPromptPanel(BasicQueryTab parentTab, int type) {
		theParentTab = parentTab;

		setColumns();
		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		setAlignmentX(Component.LEFT_ALIGNMENT);
		setBackground(Color.white);
		
		columnDataPanel = new ColumnSelectionPanel();
		annoDBPanel = new AnnoSelectionPanel();
		speciesPanel = new SpeciesSelectionPanel();
		attributePanel = new AttributePanel();

		theSetViewPanel = new SetViewPanel();
		theSearchPanel = new SearchPanel(type);
		theFilterPanel = new FilterPanel();
		theResultsPanel = new ResultsPanel();

		setButtonPanel();
		if(type == BasicQueryTab.VIEW_BY_HIT)
			nViewMode = VIEW_MODE_INDIVIDUAL_HIT;
		else
			nViewMode = VIEW_MODE_GROUP_CONTIG;
		
		columnDataPanel.buildUI();
		annoDBPanel.buildUI();
		speciesPanel.buildUI();
		attributePanel.buidUI();
		
		addLocalListeners();
		
		theSetViewPanel.addActionListenerForGroupSelect(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				updateViewMode();
				theParentTab.update();
			}
		});
		add(annoDBPanel);
		add(columnDataPanel);
		add(attributePanel);
		add(speciesPanel);
		
		add(Box.createVerticalStrut(10));
		add(theSearchPanel);
		add(Box.createVerticalStrut(5));
		add(theFilterPanel);
		add(Box.createVerticalStrut(5));
		add(theResultsPanel);		
		add(Box.createVerticalStrut(5));
		add(theSetViewPanel);
	}
	
	public String [] getLibraryNames() { return lSetNames; }
	public String [] getContigSetNames() { return uSetNames; }
	
	public String [] getAllColumnNames() { return columnDataPanel.getAllColumnNames(); }
	public boolean [] getAllColumnSelections() { return columnDataPanel.getAllColumnSelections(); }
	
	public String getSearchStr() { return theSearchPanel.getSearchString(); }
	public int getResultsLimit() { return theResultsPanel.getLimit(); }
	public void setAddToTableEnabled(boolean enabled) { theResultsPanel.setAddToTableEnabled(enabled); }
	
	public int getRankLimit() { return attributePanel.getRankLimit(); }
	public double getEValLimit() { return attributePanel.getEvalLimit(); }
	public boolean isBestAnnoSelected() { return attributePanel.isBestAnnoSelected(); }
	public boolean isBestEvalSelected() { return attributePanel.isBestEvalSelected(); }
	
	public boolean isKEGGSelected() { return attributePanel.isKEGGSelected(); }
	public boolean isPFAMSelected() { return attributePanel.isPFAMSelected(); }
	public boolean isECSelected() { return attributePanel.isECSelected(); }
	
	public String getKEGGSubStr() { return attributePanel.getKEGGSubStr(); }
	public String getPFAMSubStr() { return attributePanel.getPFAMSubStr(); }
	public String getECSubStr() { return attributePanel.getECSubStr(); }
	
	private void setColumns() {
		//Load library names
		if(theParentTab.getParentFrame().hasExpLevels()) 
			lSetNames = theParentTab.getParentFrame().getQueryTab().getAllLibraryNames(false);
		//Load Unitrans set names
		if(theParentTab.getParentFrame().hasContigSets()) 
			uSetNames = theParentTab.getParentFrame().getQueryTab().getAllContigSetNames(false);
		
		int numSets = ((lSetNames == null)?0:lSetNames.length);
		numSets += ((uSetNames == null)?0:uSetNames.length);
		
		String [] setNames = new String[numSets];
		int setIndex = 0;
		for(int x=0; lSetNames != null && x<lSetNames.length; x++)
			setNames[setIndex++] = lSetNames[x];
		for(int x=0; uSetNames != null && x<uSetNames.length; x++)
			setNames[setIndex++] = uSetNames[x];
		
		int nDynamicColumns = 3;
		
		indContigGeneralColumnLabels = new String[INDIVIDUAL_CONTIG_COLUMN_STATIC_NAMES.length];
		int x=0;
		for(; x<INDIVIDUAL_CONTIG_COLUMN_STATIC_NAMES.length; x++)
			indContigGeneralColumnLabels[x] = INDIVIDUAL_CONTIG_COLUMN_STATIC_NAMES[x];

		grpContigGeneralColumnLabels = new String[GROUP_CONTIG_COLUMN_STATIC_NAMES_DISPLAY.length + nDynamicColumns];
		for(x=0; x<GROUP_CONTIG_COLUMN_STATIC_NAMES_DISPLAY.length; x++)
			grpContigGeneralColumnLabels[x] = GROUP_CONTIG_COLUMN_STATIC_NAMES_DISPLAY[x];
		grpContigGeneralColumnLabels[x++] = "Best DB Hit KEGG";
		grpContigGeneralColumnLabels[x++] = "Best DB Hit PFam";
		grpContigGeneralColumnLabels[x++] = "Best DB Hit EC";
		
		indHitGeneralColumnLabels = new String[INDIVIDUAL_HIT_COLUMN_STATIC_NAMES.length + nDynamicColumns];
		for(x=0; x<INDIVIDUAL_HIT_COLUMN_STATIC_NAMES.length; x++)
			indHitGeneralColumnLabels[x] = INDIVIDUAL_HIT_COLUMN_STATIC_NAMES[x];
		indHitGeneralColumnLabels[x++] = "KEGG";
		indHitGeneralColumnLabels[x++] = "PFam";
		indHitGeneralColumnLabels[x++] = "EC";

		grpHitGeneralColumnLabels = new String[GROUP_HIT_COLUMN_STATIC_NAMES.length + nDynamicColumns];
		for(x=0; x<GROUP_HIT_COLUMN_STATIC_NAMES.length; x++)
			grpHitGeneralColumnLabels[x] = GROUP_HIT_COLUMN_STATIC_NAMES[x];
		grpHitGeneralColumnLabels[x++] = "KEGG";
		grpHitGeneralColumnLabels[x++] = "PFam";
		grpHitGeneralColumnLabels[x++] = "EC";
	}

	public String getHitSearchSummary() {
		return " (" + attributePanel.getSummary() + ", " + speciesPanel.getSummary() + ", " 
					+ annoDBPanel.getSummary() + ")";
	}
	
	public String [] getSpeciesSelected() { return speciesPanel.getSelectedSpecies(); }
	public boolean isSpeciesInclude() { return speciesPanel.isSpeciesInclude(); }
	
	public String [] getAnnoTypes() {
		if(annoDBPanel.isAllAnnoSelected()) return null;
		return annoDBPanel.getSelectedAnnoType();
	}
	
	public String [] getAnnoTaxo() {
		if(annoDBPanel.isAllAnnoSelected()) return null;
		return annoDBPanel.getSelectedAnnoTaxo();
	}
	
	public boolean isGroupedSelected() { return theSetViewPanel.isGroupSelected(); }
	public int getViewMode() { return nViewMode; }
	
	public void updateViewMode() {
		int newMode;
		if(theParentTab.getType() == BasicQueryTab.VIEW_BY_HIT) {
			if(theSetViewPanel.isGroupSelected())
				newMode = VIEW_MODE_GROUP_HIT;
			else
				newMode = VIEW_MODE_INDIVIDUAL_HIT;
		}
		else {
			if(theSetViewPanel.isGroupSelected())
				newMode = VIEW_MODE_GROUP_CONTIG;
			else
				newMode = VIEW_MODE_INDIVIDUAL_CONTIG;
		}
		setViewMode(newMode, false);
	}
	
	public void addUpdateListener(ActionListener l) {
		theSearchPanel.addListener(l);
	}
	
	public int getQueryMode() { return theSearchPanel.getQueryMode(); }
	
	public void addColumnSelectUpdateListener(ActionListener l) { columnDataPanel.setOKListener(l); }
	public void addAnnoDBUpdateListener(ActionListener l) { annoDBPanel.addOKListener(l); }
	public void addSpeciesUpdateListener(ActionListener l) { speciesPanel.addOKListener(l); }
	public void addAttributeUpdateListener(ActionListener l) { attributePanel.addOKListener(l); }
	
	public void addColumnSelectShowListener(ActionListener l) { columnDataPanel.setCancelListener(l); }
	public void addAnnoDBShowListener(ActionListener l) { annoDBPanel.addCancelListener(l); }
	public void addSpeciesShowListener(ActionListener l) { speciesPanel.addCancelListener(l); }
	public void addAttributeShowListener(ActionListener l) { attributePanel.addCancelListener(l); }
	
	public void addColumnSelectHideListener(ActionListener l) { theSetViewPanel.addActionListenerForColumnSelect(l); }
	public void addAnnoDBHideListener(ActionListener l) { theFilterPanel.addActionListenerForAnnoDBSelect(l); }
	public void addAttributeHideListener(ActionListener l) { theFilterPanel.addActionListenerForAttributeSelect(l); }
	public void addSpeciesHideListener(ActionListener l) { theFilterPanel.addActionListenerForSpeciesSelect(l); }
	
	private void addLocalListeners() {
		columnDataPanel.setOKListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				theSetViewPanel.setVisible(true);
				theSearchPanel.setVisible(true);
				theFilterPanel.setVisible(true);
				theResultsPanel.setVisible(true);
				columnDataPanel.setVisible(false);
			}
		});
		columnDataPanel.setCancelListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				theSetViewPanel.setVisible(true);
				theSearchPanel.setVisible(true);
				theFilterPanel.setVisible(true);
				theResultsPanel.setVisible(true);
				columnDataPanel.setVisible(false);
			}
		});
		annoDBPanel.addOKListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				theSetViewPanel.setVisible(true);
				theSearchPanel.setVisible(true);
				theFilterPanel.setVisible(true);
				theResultsPanel.setVisible(true);
				annoDBPanel.setVisible(false);
			}
		});
		annoDBPanel.addCancelListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				theSetViewPanel.setVisible(true);
				theSearchPanel.setVisible(true);
				theFilterPanel.setVisible(true);
				theResultsPanel.setVisible(true);
				annoDBPanel.setVisible(false);
			}
		});
		attributePanel.addOKListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				theSetViewPanel.setVisible(true);
				theSearchPanel.setVisible(true);
				theFilterPanel.setVisible(true);
				theResultsPanel.setVisible(true);
				attributePanel.setVisible(false);
			}
		});
		attributePanel.addCancelListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				theSetViewPanel.setVisible(true);
				theSearchPanel.setVisible(true);
				theFilterPanel.setVisible(true);
				theResultsPanel.setVisible(true);
				attributePanel.setVisible(false);
			}
		});
		
		speciesPanel.addOKListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				theSetViewPanel.setVisible(true);
				theSearchPanel.setVisible(true);
				theFilterPanel.setVisible(true);
				theResultsPanel.setVisible(true);
				speciesPanel.setVisible(false);
			}
		});
		speciesPanel.addCancelListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				theSetViewPanel.setVisible(true);
				theSearchPanel.setVisible(true);
				theFilterPanel.setVisible(true);
				theResultsPanel.setVisible(true);
				speciesPanel.setVisible(false);
			}
		});
	}
	
	private void setButtonPanel() {
		theSetViewPanel.addActionListenerForColumnSelect(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				theSetViewPanel.setVisible(false);
				theSearchPanel.setVisible(false);
				theFilterPanel.setVisible(false);
				theResultsPanel.setVisible(false);
				columnDataPanel.promptUser();
			}
		});
		theFilterPanel.addActionListenerForAnnoDBSelect(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				theSetViewPanel.setVisible(false);
				theSearchPanel.setVisible(false);
				theFilterPanel.setVisible(false);
				theResultsPanel.setVisible(false);
				annoDBPanel.promptUser();
			}
		});
		theFilterPanel.addActionListenerForSpeciesSelect(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				theSetViewPanel.setVisible(false);
				theSearchPanel.setVisible(false);
				theFilterPanel.setVisible(false);
				theResultsPanel.setVisible(false);
				speciesPanel.promptUser();
			}
		});
		theFilterPanel.addActionListenerForAttributeSelect(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				theSetViewPanel.setVisible(false);
				theSearchPanel.setVisible(false);
				theFilterPanel.setVisible(false);
				theResultsPanel.setVisible(false);
				attributePanel.promptUser();
			}
		});
	}
	
	private void setViewMode(int mode, boolean firstCall) {
		if(!firstCall)
			saveState();
		loadState(mode);
		
		if(mode == VIEW_MODE_INDIVIDUAL_CONTIG)
			theParentTab.setBuriedReadVisible(true);
		else
			theParentTab.setBuriedReadVisible(false);
	}
	
	private void saveState() {
		switch(nViewMode) {
		case VIEW_MODE_INDIVIDUAL_HIT:		
			strIndividualHitColumnSelections = columnDataPanel.getColumnSelections();
			break;
		case VIEW_MODE_INDIVIDUAL_CONTIG: 	
			strIndividualContigColumnSelections = columnDataPanel.getColumnSelections();
			break;
		case VIEW_MODE_GROUP_HIT: 			
			strGroupHitColumnSelections = columnDataPanel.getColumnSelections();									
			break;
		case VIEW_MODE_GROUP_CONTIG: 		
			strGroupContigColumnSelections = columnDataPanel.getColumnSelections();
			break;
		}
	}
	
	private void loadState(int newMode) {
		switch(newMode) {
		case VIEW_MODE_INDIVIDUAL_HIT:		
			columnDataPanel.setColumnNames(indHitGeneralColumnLabels, lSetNames, uSetNames);
			columnDataPanel.setColumnSelections(strIndividualHitColumnSelections);
			break;
		case VIEW_MODE_INDIVIDUAL_CONTIG:	
			columnDataPanel.setColumnNames(indContigGeneralColumnLabels, null, null);
			columnDataPanel.setColumnSelections(strIndividualContigColumnSelections);
			break;
		case VIEW_MODE_GROUP_HIT: 			
			columnDataPanel.setColumnNames(grpHitGeneralColumnLabels, lSetNames, uSetNames);
			columnDataPanel.setColumnSelections(strGroupHitColumnSelections);
			break;
		case VIEW_MODE_GROUP_CONTIG:		
			columnDataPanel.setColumnNames(grpContigGeneralColumnLabels, lSetNames, uSetNames);
			columnDataPanel.setColumnSelections(strGroupContigColumnSelections);
			break;
		}
		nViewMode = newMode;
	}
	private class AnnoSelectionPanel extends JPanel
	{
		private static final long serialVersionUID = 1L;
		public AnnoSelectionPanel() {}
		
		public String getSummary() { 
			if (getNumSelectedAnnoDB()==chkAnnoDB.length) return " all annoDBs";
			return getNumSelectedAnnoDB() + " annoDBs selected"; 
		}
		public void buildUI() {
			setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
			setAlignmentX(Component.CENTER_ALIGNMENT);
			setAlignmentY(Component.CENTER_ALIGNMENT);
			setBackground(Color.white);
			
			add(Box.createVerticalStrut(30));
			add(createHeaderPanel());
			add(Box.createVerticalStrut(10));
			add(createAnnoSelectPanel());
			add(Box.createVerticalStrut(10));
			add(createButtonPanel());
			
			setMaximumSize(getPreferredSize());
			setVisible(false);
		}
		
		public JPanel createHeaderPanel() {
			JPanel retVal = new JPanel();
			retVal.setBackground(BGCOLOR);
			retVal.setLayout(new BoxLayout(retVal, BoxLayout.LINE_AXIS));
			
			JLabel theHeader = new JLabel("<HTML><H2>Select Anno DBs to use</H2></HTML>");
			theHeader.setAlignmentX(Component.CENTER_ALIGNMENT);
			retVal.add(theHeader);
			retVal.add(Box.createVerticalStrut(10));
			retVal.setMaximumSize(retVal.getPreferredSize());
			retVal.setAlignmentX(Component.CENTER_ALIGNMENT);

			return retVal;
		}
		
		private void saveSelection() {
			selectionBuffer = new boolean[chkAnnoDB.length];
			for(int x=0; x<chkAnnoDB.length; x++) {
				selectionBuffer[x] = chkAnnoDB[x].isSelected();
			}
		}
		
		private void restoreSelection() {
			for(int x=0; x<chkAnnoDB.length; x++)
				chkAnnoDB[x].setSelected(selectionBuffer[x]);
		}
		
		// XXX Anno Select Panel
		private JPanel createAnnoSelectPanel() {
			String [] annoDBs = theParentTab.getAnnoDBs();
			JPanel retVal = new JPanel();
			retVal.setBackground(BGCOLOR);
			retVal.setLayout(new BoxLayout(retVal, BoxLayout.PAGE_AXIS));
			retVal.setAlignmentX(Component.CENTER_ALIGNMENT);
			
			chkAnnoDB = new JCheckBox[annoDBs.length/2];
			lblTaxo = new JLabel[annoDBs.length/2];
			
			JPanel row = new JPanel();
			row.setBackground(BGCOLOR);
			row.setLayout(new BoxLayout(row, BoxLayout.LINE_AXIS));
			row.setAlignmentX(Component.LEFT_ALIGNMENT);
			
			retVal.add(new JSeparator());
			int index = 0;
			for(int x=0; x<chkAnnoDB.length; x++) {
				chkAnnoDB[x] = new JCheckBox(annoDBs[index++]);
				chkAnnoDB[x].setBackground(BGCOLOR);
				chkAnnoDB[x].addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						if(isAllAnnoSelected())
							selectAll.setSelected(true);
						else
							selectAll.setSelected(false);
					}
				});
				chkAnnoDB[x].setSelected(true);
				lblTaxo[x] = new JLabel(annoDBs[index++]);
				JPanel selection = new JPanel();
				selection.setBackground(BGCOLOR);
				selection.setLayout(new BoxLayout(selection, BoxLayout.LINE_AXIS));
				selection.setAlignmentX(Component.LEFT_ALIGNMENT);
				selection.add(chkAnnoDB[x]);
				selection.add(new JLabel("--"));
				selection.add(lblTaxo[x]);
				if(selection.getPreferredSize().width < ANNODB_COLUMN_WIDTH)
					selection.add(Box.createHorizontalStrut(ANNODB_COLUMN_WIDTH-selection.getPreferredSize().width));
				selection.setMaximumSize(selection.getPreferredSize());
				row.add(selection);
				if(row.getComponentCount() == ANNODB_NUM_COLUMNS) {
					retVal.add(row);
					row = new JPanel();
					row.setBackground(BGCOLOR);
					row.setLayout(new BoxLayout(row, BoxLayout.LINE_AXIS));
					row.setAlignmentX(Component.LEFT_ALIGNMENT);
				}
			}
			if(row.getComponentCount() > 0)
				retVal.add(row);
			retVal.add(Box.createVerticalStrut(5));
			retVal.add(new JSeparator());
			selectAll = new JCheckBox("Check/Uncheck All");
			selectAll.setBackground(BGCOLOR);
			selectAll.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					for(int x=0; x<chkAnnoDB.length; x++)
						chkAnnoDB[x].setSelected(selectAll.isSelected());
				}
			});
			selectAll.setAlignmentX(Component.LEFT_ALIGNMENT);
			selectAll.setSelected(true);
			row = new JPanel();
			row.setBackground(BGCOLOR);
			row.setLayout(new BoxLayout(row, BoxLayout.LINE_AXIS));
			row.setAlignmentX(Component.LEFT_ALIGNMENT);
			row.add(selectAll);
			row.setMaximumSize(row.getPreferredSize());
			retVal.add(row);
			retVal.add(new JSeparator());
			
			retVal.setMaximumSize(retVal.getPreferredSize());
			return retVal;
		}
		
		private JPanel createButtonPanel() {
			btnOK = new JButton("Accept");
			btnOK.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					saveSelection();
				}
			});
			btnCancel = new JButton("Discard");
			btnCancel.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					restoreSelection();
				}
			});
			
			JPanel retVal = new JPanel();
			retVal.setBackground(BGCOLOR);
			retVal.setLayout(new BoxLayout(retVal, BoxLayout.LINE_AXIS));
			retVal.setAlignmentX(Component.CENTER_ALIGNMENT);
			retVal.add(btnOK);
			retVal.add(Box.createHorizontalStrut(15));
			retVal.add(btnCancel);		
			retVal.setMaximumSize(retVal.getPreferredSize());			
			return retVal;
		}
		
		public void addOKListener(ActionListener l) { btnOK.addActionListener(l); }
		public void addCancelListener(ActionListener l) { btnCancel.addActionListener(l); }
		
		public void promptUser() {
			saveSelection();
			selectAll.setSelected(isAllAnnoSelected());
			setVisible(true);
		}
		
		public boolean isAllAnnoSelected() {
			boolean retVal = true;
			
			for(int x=0; retVal && x<chkAnnoDB.length; x++)
				retVal = chkAnnoDB[x].isSelected();
			
			return retVal;
		}
		
		public int getNumSelectedAnnoDB() {
			int retVal = 0;
			for(int x=0; x<chkAnnoDB.length; x++)
				if(chkAnnoDB[x].isSelected()) retVal++;
			return retVal;
		}
		
		public String [] getSelectedAnnoType() {
			String [] retVal = new String[getNumSelectedAnnoDB()];
			int index = 0;
			for(int x=0; x<chkAnnoDB.length; x++)
				if(chkAnnoDB[x].isSelected())
					retVal[index++] = chkAnnoDB[x].getText();
			return retVal;
		}
		
		public String [] getSelectedAnnoTaxo() {
			String [] retVal = new String[getNumSelectedAnnoDB()];
			int index = 0;
			for(int x=0; x<lblTaxo.length; x++)
				if(chkAnnoDB[x].isSelected())
					retVal[index++] = lblTaxo[x].getText();
			return retVal;
		}
		
		private boolean [] selectionBuffer = null; 
		private JCheckBox [] chkAnnoDB = null;
		private JCheckBox selectAll = null;
		private JLabel [] lblTaxo = null;
		private JButton btnOK = null;
		private JButton btnCancel = null;
	}
	/// XXX Attribute Panel
	private class AttributePanel extends JPanel {
		private static final long serialVersionUID = 8503076748387692948L;
		public void buidUI() {			
			setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
			setAlignmentX(Component.CENTER_ALIGNMENT);
			setAlignmentY(Component.CENTER_ALIGNMENT);
			setBackground(Color.white);
			
			add(Box.createVerticalStrut(30));
			add(createHeaderPanel());
			add(Box.createVerticalStrut(10));
			add(createSelectionPanel());
			add(Box.createVerticalStrut(10));
			add(createButtonPanel());
			
			setMaximumSize(getPreferredSize());
			setVisible(false);
		}
		
		public String getSummary() { 
			NumberFormat formatter = new DecimalFormat("0E0");
			String ret = " Rank<=" + getRankLimit();
			if (isBestEvalSelected()) ret += ", Best Eval Evalue=" + formatter.format(getEValLimit());
			if (isBestAnnoSelected()) ret += ", Best Anno Evalue=" + formatter.format(getEValLimit());
			
			if (isKEGGSelected()) {
				if(getKEGGSubStr().length() > 0)
					ret += ", Kegg contains '" + getKEGGSubStr() + "'";
				else
					ret += ", Has Kegg result";
			}
			if (isPFAMSelected()) {
				if(getPFAMSubStr().length() > 0)
					ret += ", Pfam contains '" + getPFAMSubStr() + "'";
				else
					ret += ", Has Pfam result";
			}
			if (isECSelected()) {
				if(getECSubStr().length() > 0)
					ret += ", EC contains '" + getECSubStr() + "'";
				else
					ret += ", Has EC result";
			}
			return ret;
		}
		
		private JPanel createHeaderPanel() {
			JPanel retVal = new JPanel();
			retVal.setBackground(BGCOLOR);
			retVal.setLayout(new BoxLayout(retVal, BoxLayout.PAGE_AXIS));
			retVal.setAlignmentX(Component.CENTER_ALIGNMENT);
			
			JLabel theHeader = new JLabel("<HTML><H2>Enter attributes</H2></HTML>");
			theHeader.setAlignmentX(CENTER_ALIGNMENT);
			retVal.add(theHeader);
			retVal.add(Box.createVerticalStrut(10));
			retVal.setMaximumSize(retVal.getPreferredSize());
			retVal.setAlignmentX(CENTER_ALIGNMENT);
			add(Box.createVerticalStrut(30));
			add(retVal);
			add(Box.createVerticalStrut(10));

			return retVal;
		}
		
		private JPanel createSelectionPanel() {
			JPanel retVal = new JPanel();
			retVal.setBackground(BGCOLOR);
			retVal.setLayout(new BoxLayout(retVal, BoxLayout.PAGE_AXIS));
			retVal.setAlignmentX(Component.CENTER_ALIGNMENT);
			
			lblBestEval = new JLabel("Best Eval Hit");
			chkBestEval = new JCheckBox();
			chkBestEval.setSelected(true);
			
			lblBestAnno = new JLabel("Best Anno Hit");
			chkBestAnno = new JCheckBox();
			chkBestAnno.setSelected(false);
			
			lblEValLimit = new JLabel("Eval <= ");
			txtEValLimit = new JTextField(10);
			NumberFormat formatter = new DecimalFormat("0E0");
			txtEValLimit.setText(formatter.format(DEFAULT_EVAL_LIMIT));
			
			lblRankLimit = new JLabel("Rank <= ");
			txtRankLimit = new JTextField(5);
			txtRankLimit.setText(Integer.toString(DEFAULT_RANK_LIMIT));
			
			chkHasKEGG = new JCheckBox("Has KEGG");
			chkHasPFAM = new JCheckBox("Has PFAM");
			chkHasEC = new JCheckBox("Has EC");
			
			txtKEGG = new JTextField(10);
			txtPFAM = new JTextField(10);
			txtEC = new JTextField(10);
			
			JPanel row = new JPanel();
			row.setBackground(BGCOLOR);
			row.setLayout(new BoxLayout(row, BoxLayout.LINE_AXIS));
			row.setAlignmentX(Component.LEFT_ALIGNMENT);
			row.add(lblBestEval);
			row.add(chkBestEval);
			row.add(Box.createHorizontalStrut(30));
			row.add(lblBestAnno);
			row.add(chkBestAnno);
			row.add(Box.createHorizontalStrut(30));
			row.add(lblEValLimit);
			row.add(txtEValLimit);
			row.setMaximumSize(row.getPreferredSize());
			retVal.add(Box.createVerticalStrut(10));
			retVal.add(row);
			
			row = new JPanel();
			row.setBackground(BGCOLOR);
			row.setLayout(new BoxLayout(row, BoxLayout.LINE_AXIS));
			row.setAlignmentX(Component.LEFT_ALIGNMENT);
			row.add(lblRankLimit);
			row.add(txtRankLimit);
			row.setMaximumSize(row.getPreferredSize());
			retVal.add(Box.createVerticalStrut(10));
			retVal.add(row);
			
			row = new JPanel();
			row.setBackground(BGCOLOR);
			row.setLayout(new BoxLayout(row, BoxLayout.LINE_AXIS));
			row.setAlignmentX(Component.LEFT_ALIGNMENT);
			row.add(chkHasKEGG);
			row.add(Box.createHorizontalStrut(30));
			row.add(txtKEGG);
			row.setMaximumSize(row.getPreferredSize());
			retVal.add(Box.createVerticalStrut(10));
			retVal.add(row);
			
			row = new JPanel();
			row.setBackground(BGCOLOR);
			row.setLayout(new BoxLayout(row, BoxLayout.LINE_AXIS));
			row.setAlignmentX(Component.LEFT_ALIGNMENT);
			row.add(chkHasPFAM);
			row.add(Box.createHorizontalStrut(30));
			row.add(txtPFAM);
			row.setMaximumSize(row.getPreferredSize());
			retVal.add(Box.createVerticalStrut(10));
			retVal.add(row);
			
			row = new JPanel();
			row.setBackground(BGCOLOR);
			row.setLayout(new BoxLayout(row, BoxLayout.LINE_AXIS));
			row.setAlignmentX(Component.LEFT_ALIGNMENT);
			row.add(chkHasEC);
			row.add(Box.createHorizontalStrut(chkHasKEGG.getPreferredSize().width - chkHasEC.getPreferredSize().width));
			row.add(Box.createHorizontalStrut(30));
			row.add(txtEC);
			row.setMaximumSize(row.getPreferredSize());
			retVal.add(Box.createVerticalStrut(10));
			retVal.add(row);
			
			return retVal;
		}
		
		private JPanel createButtonPanel() {
			JPanel retVal = new JPanel();
			retVal.setBackground(BGCOLOR);
			retVal.setLayout(new BoxLayout(retVal, BoxLayout.LINE_AXIS));
			retVal.setAlignmentX(CENTER_ALIGNMENT);
			
			btnOK = new JButton("Accept");
			btnOK.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					
				}
			});
			btnCancel = new JButton("Discard");
			btnCancel.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					restoreSelections();
				}
			});
			
			retVal.add(btnOK);
			retVal.add(Box.createHorizontalStrut(10));
			retVal.add(btnCancel);
			retVal.add(Box.createHorizontalStrut(10));
						
			return retVal;
		}
		
		public void promptUser() { 
			saveSelections();
			setVisible(true);
		}
		
		private void saveSelections() {
			oldRank = getRankLimit();
			oldEval = getEvalLimit();
			strOldKEGG = getKEGGSubStr();
			strOldPFAM = getPFAMSubStr();
			strOldEC = getECSubStr();
			bOldBestEval = isBestEvalSelected();
			bOldBestAnno = isBestAnnoSelected();
			bOldKEGGSel = isKEGGSelected();
			bOldPFAMSel = isPFAMSelected();
			bOldECSel = isECSelected();
		}
		
		private void restoreSelections() {	
			if(oldRank >= 0) txtRankLimit.setText("" + oldRank);
			else		txtRankLimit.setText("100");
			chkBestAnno.setSelected(bOldBestAnno);
			chkBestEval.setSelected(bOldBestEval);
			txtKEGG.setText(strOldKEGG);
			chkHasKEGG.setSelected(bOldKEGGSel);
			txtPFAM.setText(strOldPFAM);
			chkHasPFAM.setSelected(bOldPFAMSel);
			txtEC.setText(strOldEC);
			chkHasEC.setSelected(bOldECSel);
			
			if(oldEval >= 0) {
				NumberFormat formatter = new DecimalFormat("0E0");
				txtEValLimit.setText(formatter.format(oldEval));
			}
			else
				txtEValLimit.setText("");
		}
		
		public void addOKListener(ActionListener l) { btnOK.addActionListener(l); }
		public void addCancelListener(ActionListener l) { btnCancel.addActionListener(l); }

		public int getRankLimit() {
			if(txtRankLimit.getText().length() > 0)
				return Integer.parseInt(txtRankLimit.getText());
			return -1;
		}
		public double getEvalLimit() { 
			if(txtEValLimit.getText().length() > 0)
				return Double.parseDouble(txtEValLimit.getText());
			return -1;
		}
		public boolean isBestAnnoSelected() {
			return chkBestAnno.isSelected();
		}
		public boolean isBestEvalSelected() {
			return chkBestEval.isSelected();
		}
		
		public boolean isKEGGSelected() { return chkHasKEGG.isSelected(); }
		public boolean isPFAMSelected() { return chkHasPFAM.isSelected(); }
		public boolean isECSelected() { return chkHasEC.isSelected(); }
		
		public String getKEGGSubStr() { return txtKEGG.getText(); }
		public String getPFAMSubStr() { return txtPFAM.getText(); }
		public String getECSubStr() { return txtEC.getText(); }
		
		private JTextField txtRankLimit = null;
		private JTextField txtEValLimit = null;
		private int oldRank;
		private double oldEval;
		private JLabel lblRankLimit = null, lblEValLimit = null;
		private JLabel lblBestAnno = null, lblBestEval=null;		
		private JButton btnOK = null;
		private JButton btnCancel = null;
		private JCheckBox chkBestAnno = null;
		private JCheckBox chkBestEval = null;
		
		private JCheckBox chkHasKEGG = null;
		private JCheckBox chkHasPFAM = null;
		private JCheckBox chkHasEC = null;
		
		private JTextField txtKEGG = null;
		private JTextField txtPFAM = null;
		private JTextField txtEC = null;
		
		private String strOldKEGG = "";
		private String strOldPFAM = "";
		private String strOldEC = "";
		
		private boolean bOldBestEval = false;
		private boolean bOldBestAnno = false;
		private boolean bOldKEGGSel = false;
		private boolean bOldPFAMSel = false;
		private boolean bOldECSel = false;
	}
	
	private class SpeciesSelectionPanel extends JPanel {
		private static final long serialVersionUID = 3047222803816003422L;
		public SpeciesSelectionPanel() {
			sl = new ListSelectionListener() {
				public void valueChanged(ListSelectionEvent e) {
					update();
				}
			};
			
			lInc = new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					incList.addValues(exList.getSelectedValues());
					exList.removeSelectedValues();
					update();
				}
			};
			
			lEx = new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					exList.addValues(incList.getSelectedValues());
					incList.removeSelectedValues();
					update();
				}
			};
			
			lUpdate = new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					update();
				}
			};
		}
		
		public String getSummary() {
			if (exList.getNumElements() == 0) return " all species";
			return exList.getNumElements() + " species " + 
						(exList.isInclude()?"Included":"Excluded");
		}
		
		private void update() {
			int incNumSel = incList.getNumSelectedElements();
			int exNumSel = exList.getNumSelectedElements();

			int incNum = incList.getNumSpecies();
			int exNum = exList.getNumSpecies();
			
			if(incNumSel > 0)
				movePanel.setRemoveEnabled(true);
			else
				movePanel.setRemoveEnabled(false);
				
			if(exNumSel > 0)
				movePanel.setAddEnabled(true);
			else
				movePanel.setAddEnabled(false);
			
			String statusText = "";
			if(incNum == 0)
				statusText = "No Species";
			else {
				statusText = incNum + " Species";
			}
			incList.setStatus(statusText);
			String modeStr = "";
			if(exList.isInclude())
				modeStr = "Included";
			else
				modeStr = "Excluded";
			
			if(exNum == 0)
				statusText = "No Species " + modeStr;
			else {
				statusText = exNum + " Species " + modeStr;
			}
			exList.setStatus(statusText);
		}
		
		public void buildUI() {
			setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
			setAlignmentX(Component.CENTER_ALIGNMENT);
			setAlignmentY(Component.CENTER_ALIGNMENT);
			setBackground(Color.white);
			add(createHeaderPanel());
			add(Box.createVerticalStrut(30));
			add(createSelectPanel());
			add(Box.createVerticalStrut(10));
			
			add(createButtonPanel());
			setMaximumSize(getPreferredSize());
			setVisible(false);
		}
		
		public String [] getSelectedSpecies() { return exList.getAllValues(); }
		public boolean isSpeciesInclude() { return exList.isInclude(); }
		
		private JPanel createHeaderPanel() {
			JPanel retVal = new JPanel();
			retVal.setBackground(BGCOLOR);
			retVal.setLayout(new BoxLayout(retVal, BoxLayout.LINE_AXIS));
			
			JLabel theHeader = new JLabel("<HTML><H2>Select species to view</H2></HTML>");
			theHeader.setAlignmentX(CENTER_ALIGNMENT);
			retVal.add(theHeader);
			retVal.add(Box.createVerticalStrut(10));
			retVal.setMaximumSize(retVal.getPreferredSize());
			retVal.setAlignmentX(CENTER_ALIGNMENT);

			return retVal;
		}
		
		private JPanel createButtonPanel() {
			btnOK = new JButton("Accept");
			btnOK.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					
				}
			});
			btnCancel = new JButton("Discard");
			btnCancel.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					restoreSelections();
				}
			});
			
			JPanel buttonPanel = new JPanel();
			buttonPanel.setBackground(BGCOLOR);
			buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
			buttonPanel.add(btnOK);
			buttonPanel.add(Box.createHorizontalStrut(10));
			buttonPanel.add(btnCancel);
			
			buttonPanel.setMaximumSize(buttonPanel.getPreferredSize());
			buttonPanel.setAlignmentX(CENTER_ALIGNMENT);
			
			return buttonPanel;
		}
		
		private void saveSelections() {
			oldInc = incList.getAllValues();
			oldEx = exList.getAllValues();
			oldModeInc = exList.isInclude();
		}
		
		private void restoreSelections() {
			incList.setAllValues(oldInc);
			exList.setAllValues(oldEx);
			exList.setInclude(oldModeInc);
		}
		
		private JPanel createSelectPanel() {
			JPanel retVal = new JPanel();			
			retVal.setBackground(BGCOLOR);
			
			incList = new SpeciesListPanel(SpeciesListPanel.LIST_ONLY, "Species List");
			exList = new SpeciesListPanel(SpeciesListPanel.MODE_SEL, "");
			
			incList.addValues(theParentTab.getSpecies());
			incList.addChangeListener(sl);
			exList.addChangeListener(sl);
			exList.addActionListenerForModeSelect(lUpdate);
			movePanel = new SpeciesMovePanel();
			movePanel.addActionListenerForAdd(lInc);
			movePanel.addActionListenerForRemove(lEx);
			
			retVal.add(incList);
			retVal.add(movePanel);
			retVal.add(exList);
			
			return retVal;
		}
		public void addOKListener(ActionListener l) { btnOK.addActionListener(l); }
		public void addCancelListener(ActionListener l) { btnCancel.addActionListener(l); }

		public void promptUser() {
			saveSelections();
			update();
			setVisible(true);
		}
		private JButton btnOK = null, btnCancel = null;
		private SpeciesListPanel incList = null, exList = null;
		private SpeciesMovePanel movePanel = null;
		private String [] oldInc = null;
		private String [] oldEx = null;
		private boolean oldModeInc = false;
		private ListSelectionListener sl = null;
		private ActionListener lInc = null;
		private ActionListener lEx = null;
		private ActionListener lUpdate = null;

		private class SpeciesListPanel extends JPanel {
			private static final long serialVersionUID = -7638735027037420167L;
			public static final int LIST_ONLY = 0;
			public static final int MODE_SEL = 1;
			
			public SpeciesListPanel(int mode, String label) {
				setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
				setBackground(Color.white);
				
				txtCount = new JTextField(10);
				txtCount.setEnabled(false);
				Dimension dim = txtCount.getPreferredSize();
				dim.width = WIDTH;
				dim.height = HEIGHT;
				theModel = new DefaultListModel();
				theList = new JList(theModel);
				listScroll = new JScrollPane(theList);
				listScroll.setPreferredSize(dim);
				listScroll.setMaximumSize(dim);
				
				add(createLabelPanel(mode, label));
				add(txtCount);
				add(Box.createVerticalStrut(5));
				add(listScroll);
				add(Box.createVerticalStrut(5));
				add(createSearchPanel());
				
				setMaximumSize(getPreferredSize());
			}
			
			public int getNumSelectedElements() {
				return theList.getSelectedIndices().length;
			}
			
			public int getNumElements() {
				return theList.getModel().getSize();				
			}
			
			public int getNumSpecies() {
				return theModel.size();
			}
			
			public void setStatus(String text) { txtCount.setText(text); }
			
			private JPanel createLabelPanel(int mode, String label) {
				JPanel retVal = new JPanel();
				retVal.setBackground(BGCOLOR);
				retVal.setLayout(new BoxLayout(retVal, BoxLayout.LINE_AXIS));
				retVal.setAlignmentX(Component.CENTER_ALIGNMENT);
				
				if(mode == LIST_ONLY) {
					lblHeader = new JLabel(label);
					lblHeader.setAlignmentX(Component.LEFT_ALIGNMENT);
					retVal.add(lblHeader);
				} else if(mode == MODE_SEL) {
					chkInclude = new JRadioButton("Include");
					chkExclude = new JRadioButton("Exclude");
					chkInclude.setSelected(true);
					ButtonGroup incExGroup = new ButtonGroup();
					incExGroup.add(chkInclude);
					incExGroup.add(chkExclude);
					retVal.add(chkInclude);
					retVal.add(chkExclude);
				}
				
				Dimension dim = retVal.getPreferredSize();
				dim.width = WIDTH;
				
				retVal.setPreferredSize(dim);
				retVal.setMaximumSize(dim);
				
				return retVal;
			}
			
			public boolean isInclude() { 
				if(chkInclude != null)
					return chkInclude.isSelected();
				return false;
			}
			
			public void setInclude(boolean include) { 
				if(chkInclude != null) {
					chkInclude.setSelected(include);
					chkExclude.setSelected(!include);
				}
			}
			
			public void addActionListenerForModeSelect(ActionListener l) {
				if(chkInclude != null) {
					chkInclude.addActionListener(l);
					chkExclude.addActionListener(l);
				}
			}
			
			public String []  getAllValues() {
				String [] retVal = new String[theModel.getSize()];
				for(int x=0; x< theModel.getSize(); x++)
					retVal[x] = (String)theModel.getElementAt(x);
				
				return retVal;
			}
			
			public void setAllValues(String [] values) {
				theModel.clear();
				for(int x=0; x<values.length; x++)
					theModel.addElement(values[x]);
			}
			
			public Vector<String> getSelectedValues() {
				Vector<String> retVal = new Vector<String> ();
				int [] vals = theList.getSelectedIndices();
				
				for(int x=0; x<vals.length; x++)
					retVal.add((String)theModel.getElementAt(vals[x]));
				
				return retVal;
			}
			
			public void removeSelectedValues() {
				Vector<String> saveVals = new Vector<String> ();
				for(int x=0; x<theModel.getSize(); x++) {
					if(!theList.isSelectedIndex(x))
						saveVals.add((String)theModel.elementAt(x));
				}
				theModel.clear();
				Iterator<String> iter = saveVals.iterator();
				while(iter.hasNext()) {
					theModel.addElement(iter.next());
				}
			}
			
			public void addValues(Vector<String> vals) {
				Vector<String> theList = new Vector<String> ();
				for(int x=0; x < theModel.getSize(); x++)
					theList.add((String)theModel.getElementAt(x));
				theModel.clear();
				theList.addAll(vals);
				Collections.sort(theList);
				Iterator<String> strIter = theList.iterator();
				while(strIter.hasNext())
					theModel.addElement(strIter.next());
				theList.clear();
			}
			
			private void selectBySubString(String subStr) {
				Vector<Integer> selections = new Vector<Integer> ();
				theList.clearSelection();
				String s="";
				try {
					for (int i=0; i< subStr.length(); i++)
						if (subStr.charAt(i) != '*') s += subStr.charAt(i);
	
					for(int x=0; x<theModel.getSize(); x++) {
						if(((String)theModel.elementAt(x)).matches("(?i)" + s + ".*"))
							selections.add(x);
					}
					int [] selArr = new int[selections.size()];
					Iterator<Integer> iter = selections.iterator();
					int index = 0;
					while(iter.hasNext()) {
						selArr[index++] = iter.next();
					}
					theList.setSelectedIndices(selArr);
				} 
				catch (Exception e) {
					String msg="Error parsing " + subStr;
					System.err.println(msg);
			   		ErrorReport.reportError(e,msg);
				}
			}
	
			private void selectBySubStringX(String subStr) {
				Vector<Integer> selections = new Vector<Integer> ();
				theList.clearSelection();
				
				for(int x=0; x<theModel.getSize(); x++) {
					try{ 
						if(((String)theModel.elementAt(x)).matches("(?i)" + subStr + ".*"))
							selections.add(x);
					} catch(Exception e) {
						String msg="Error parsing " + subStr;
						System.err.println(msg);
				   		ErrorReport.reportError(e,msg);
					}
				}
			}
			
			private String parseSearchString(String pattern) {
				pattern = pattern.replaceAll("\\*", ".*");
				return pattern;
			}
			
			private JPanel createSearchPanel() {
				JPanel retVal = new JPanel();
				retVal.setBackground(BGCOLOR);
				retVal.setLayout(new BoxLayout(retVal, BoxLayout.LINE_AXIS));
				
				btnSelect = new JButton("Highlight");
				btnSelect.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent arg0) {
						selectBySubString(txtFilter.getText());
					}
				});
				btnSelect.setMargin(new Insets(0, 0, 0, 0));
				btnSelect.setFont(new Font(btnSelect.getFont().getName(),Font.PLAIN,10));
				
				txtFilter = new JTextField(20);
				retVal.add(btnSelect);
				retVal.add(Box.createHorizontalStrut(3));
				retVal.add(txtFilter);
				
				retVal.setMaximumSize(retVal.getPreferredSize());
				
				return retVal;
			}
			
			public void addChangeListener(ListSelectionListener l) { theList.addListSelectionListener(l); }
			
			private final static int WIDTH = 300;
			private final static int HEIGHT = 400;
			private JTextField txtCount = null;
			private JList theList = null;
			private DefaultListModel theModel = null;
			private JScrollPane listScroll = null;
			private JButton btnSelect = null;
			private JTextField txtFilter = null;
			private JLabel lblHeader = null;
			private JRadioButton chkInclude = null, chkExclude = null;
		}
	
		private class SpeciesMovePanel extends JPanel {
			private static final long serialVersionUID = 6922755071089126369L;
			
			public SpeciesMovePanel() {
				setBackground(Color.white);
				setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
				btnRemove = new JButton("-->");
				btnRemove.setBackground(Color.white);
				btnAdd = new JButton("<--");
				btnAdd.setBackground(Color.white);
				
				add(btnRemove);
				add(Box.createVerticalStrut(50));
				add(btnAdd);
			}
			
			public void setRemoveEnabled(boolean enabled) { btnRemove.setEnabled(enabled); }
			public void setAddEnabled(boolean enabled) { btnAdd.setEnabled(enabled); }
			
			public void addActionListenerForRemove(ActionListener l) { btnRemove.addActionListener(l); }
			public void addActionListenerForAdd(ActionListener l) { btnAdd.addActionListener(l); }
			
			private JButton btnRemove = null, btnAdd = null;
		}
	}
	
	/// XXX Column Select Panel
	private class ColumnSelectionPanel extends JPanel
	{
		private static final long serialVersionUID = -49938519942155818L;

		private boolean firstLoad = true;
		
		public ColumnSelectionPanel() {
		}
		
		public void buildUI() {
			setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
			setBackground(Color.white);
			setAlignmentX(Component.CENTER_ALIGNMENT);
			setAlignmentY(Component.CENTER_ALIGNMENT);
			
			JPanel headerPanel = new JPanel();
			headerPanel.setLayout(new BoxLayout(headerPanel, BoxLayout.LINE_AXIS));
			headerPanel.setBackground(Color.white);
			
			JLabel theHeader = new JLabel("<HTML><H2>Select columns to view</H2></HTML>");
			theHeader.setBackground(Color.white);
			theHeader.setAlignmentX(CENTER_ALIGNMENT);
			headerPanel.add(theHeader);
			headerPanel.add(Box.createVerticalStrut(10));
			headerPanel.setMaximumSize(headerPanel.getPreferredSize());
			headerPanel.setAlignmentX(CENTER_ALIGNMENT);
			add(Box.createVerticalStrut(30));
			add(headerPanel);
			add(Box.createVerticalStrut(10));
			
			if(theParentTab.getType() == BasicQueryTab.VIEW_BY_HIT) {
				if(!theSetViewPanel.isGroupSelected())
					setViewMode(VIEW_MODE_INDIVIDUAL_HIT, firstLoad);
				else
					setViewMode(VIEW_MODE_GROUP_HIT, firstLoad);
			}
			else {
				if(!theSetViewPanel.isGroupSelected())
					setViewMode(VIEW_MODE_INDIVIDUAL_CONTIG, firstLoad);
				else
					setViewMode(VIEW_MODE_GROUP_CONTIG, firstLoad);
			}	
			
			add(columnSelectPanel);
			add(Box.createVerticalStrut(30));
			btnOK = new JButton("Accept");
			btnOK.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					
				}
			});
			btnCancel = new JButton("Discard");
			btnCancel.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					restoreSelections();
				}
			});
			
			JPanel buttonPanel = new JPanel();
			buttonPanel.setBackground(Color.white);
			buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
			buttonPanel.add(btnOK);
			buttonPanel.add(Box.createHorizontalStrut(10));
			buttonPanel.add(btnCancel);
			buttonPanel.setMaximumSize(buttonPanel.getPreferredSize());
			buttonPanel.setAlignmentX(CENTER_ALIGNMENT);
			add(buttonPanel);
			setVisible(false);
			firstLoad = false;
		}
		
		public void promptUser() {
			saveSelections();			
			setVisible(true);
			generalPanel.setVisible(true);
			libAndSetPanel.setVisible(true);
			columnSelectPanel.setVisible(true);
		}
		
		// Accept is enabled if nothing is selected
		private void setOKEnabled() {
			boolean enable = false;
			for(int x=0; !enable && x<generalColumnLabels.length; x++)
				enable = generalColumnLabels[x].isSelected();
			for(int x=0; !enable && x<lSetColumnLabels.length; x++)
				enable = lSetColumnLabels[x].isSelected();
			for(int x=0; !enable && x<uSetColumnLabels.length; x++)
				enable = uSetColumnLabels[x].isSelected();
			
			btnOK.setEnabled(enable);
		}
		
		private void setCheckBoxWidth(JCheckBox box) {
			Dimension d = box.getPreferredSize();
			if(d.width < COLUMN_SELECT_WIDTH)
				d.width = COLUMN_SELECT_WIDTH;
			box.setPreferredSize(d);
		}
		// XXX Column data
 		public void setColumnNames(String [] generalNames, String [] librarySetNames, 
 				String [] unitransSetNames) {
			if(columnSelectPanel == null) columnSelectPanel = new JPanel();
			else columnSelectPanel.removeAll();
			columnSelectPanel.setBackground(Color.white);
	
		/** General **/ 
			generalPanel = new JPanel();
			generalPanel.setBackground(Color.white);
			generalPanel.setLayout(new BoxLayout(generalPanel, BoxLayout.Y_AXIS));
			generalPanel.setAlignmentY(TOP_ALIGNMENT);
			
			JPanel gen = createPanel(true);
			gen.setBackground(Color.white);
			gen.add(Box.createHorizontalStrut(COLUMN_LEFT_MARGIN));
			gen.add(new JLabel("General"));
			generalPanel.add(gen);
			generalPanel.add(Box.createVerticalStrut(5));
			
			if(generalColumnLabels != null)
				for(int x=0; x<generalColumnLabels.length; x++)
					generalColumnLabels[x] = null;
			generalColumnLabels = new JCheckBox[generalNames.length];		
			// only check the first N General columns to be on
			// this is shared by both Basic Sequence and Basic DB Hits
			for(int x=0; x<generalNames.length; x++) {
				boolean check = (x <= NGENERAL) ? true: false;
				if (generalNames[x].equals("Remark")) check = false; // kludge
				generalColumnLabels[x] = new JCheckBox(generalNames[x], check);
				generalColumnLabels[x].setAlignmentX(LEFT_ALIGNMENT);
				generalColumnLabels[x].addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						setOKEnabled();
					}
				});
				gen = createPanel(true);
				gen.add(Box.createHorizontalStrut(COLUMN_LEFT_MARGIN));
				gen.add(generalColumnLabels[x]);
				generalPanel.add(gen);
			}
			
			JPanel genCheck = createPanel(true);
			genCheck.setBackground(Color.white);
			genCheck.add(Box.createHorizontalStrut(COLUMN_LEFT_MARGIN));
			
			final JCheckBox sAll = new JCheckBox("check/uncheck all", true);
			sAll.setAlignmentX(LEFT_ALIGNMENT);
			sAll.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					for(int x=0; x<generalColumnLabels.length; x++)
						generalColumnLabels[x].setSelected(sAll.isSelected());
					setOKEnabled();
				}
			});
			genCheck.add(sAll);
			genCheck.setBorder(BorderFactory.createLineBorder(Color.BLACK));	
			generalPanel.add(genCheck);	
			
			generalPanel.setMaximumSize(generalPanel.getPreferredSize());
			generalPanel.setAlignmentX(CENTER_ALIGNMENT);

		/** Second panel Libraries and Sets **/
			libAndSetPanel = new JPanel();
			libAndSetPanel.setBackground(Color.white);
			libAndSetPanel.setLayout(new BoxLayout(libAndSetPanel, BoxLayout.Y_AXIS));
			libAndSetPanel.setAlignmentY(TOP_ALIGNMENT);
		
			if(lSetColumnLabels != null)
				for(int x=0; x<lSetColumnLabels.length; x++)
					lSetColumnLabels[x] = null;
			
			if(librarySetNames != null) lSetColumnLabels = new JCheckBox[librarySetNames.length];
			else lSetColumnLabels = null;
			
			if(uSetColumnLabels != null)
				for(int x=0; x<uSetColumnLabels.length; x++)
					uSetColumnLabels[x] = null;

			if(unitransSetNames != null) uSetColumnLabels = new JCheckBox[unitransSetNames.length];
			else uSetColumnLabels = null;
			
			if(librarySetNames != null && librarySetNames.length > 0) {
				JPanel lib = createPanel(true);
				lib.add(Box.createHorizontalStrut(COLUMN_LEFT_MARGIN));
				lib.add(new JLabel("Library RPKM"));
				libAndSetPanel.add(lib);		
						
				// All RPKM are checked by default
				for(int x=0; x<librarySetNames.length; x++) {
					lSetColumnLabels[x] = new JCheckBox(librarySetNames[x], true);
					lSetColumnLabels[x].setAlignmentX(LEFT_ALIGNMENT);
					lSetColumnLabels[x].addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							setOKEnabled();
						}
					});
				
					JPanel libx = createPanel(true);
					libx.add(Box.createHorizontalStrut(COLUMN_LEFT_MARGIN));
					libx.add(lSetColumnLabels[x]);
					libAndSetPanel.add(libx);
				}
				JPanel libCheck = createPanel(true);
				libCheck.add(Box.createHorizontalStrut(COLUMN_LEFT_MARGIN));
				final JCheckBox selAll = new JCheckBox("check/uncheck all", true);
				
				selAll.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent arg0) {
						for(int x=0; x<lSetColumnLabels.length; x++)
							lSetColumnLabels[x].setSelected(selAll.isSelected());
						setOKEnabled();
					}
				});
				libCheck.add(selAll);
				libCheck.setBorder(BorderFactory.createLineBorder(Color.BLACK));	
				libAndSetPanel.add(libCheck);
				libAndSetPanel.add(Box.createVerticalStrut(5));
			}
			
			if(unitransSetNames != null && unitransSetNames.length > 0) {
				libAndSetPanel.add(Box.createVerticalStrut(5));
				JPanel set = createPanel(true);
				set.add(Box.createHorizontalStrut(COLUMN_LEFT_MARGIN));
				set.add(new JLabel("Sequence Set"));
				libAndSetPanel.add(set);		
				
				// The Sets are not checked by default
				for(int x=0; x<unitransSetNames.length; x++) {
					uSetColumnLabels[x] = new JCheckBox(unitransSetNames[x], false);
					uSetColumnLabels[x].setAlignmentX(LEFT_ALIGNMENT);
					uSetColumnLabels[x].addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							setOKEnabled();
						}
					});
					setCheckBoxWidth(uSetColumnLabels[x]);
					uSetColumnLabels[x].setSelected(false);
					set = createPanel(true);
					set.add(Box.createHorizontalStrut(COLUMN_LEFT_MARGIN));
					set.add(uSetColumnLabels[x]);
					libAndSetPanel.add(set);
				}				
				JPanel setCheck = createPanel(true);
				setCheck.add(Box.createHorizontalStrut(COLUMN_LEFT_MARGIN));
				final JCheckBox selAll = new JCheckBox("check/uncheck all");
				selAll.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent arg0) {
						for(int x=0; x<uSetColumnLabels.length; x++)
							uSetColumnLabels[x].setSelected(selAll.isSelected());
						setOKEnabled();
					}
				});
				setCheck.add(selAll);
				setCheck.setBorder(BorderFactory.createLineBorder(Color.BLACK));			
				libAndSetPanel.add(setCheck);
				libAndSetPanel.add(Box.createVerticalStrut(5));
			}
			libAndSetPanel.setMaximumSize(libAndSetPanel.getPreferredSize());
			libAndSetPanel.setAlignmentX(CENTER_ALIGNMENT); 
			
			if(columnSelectPanel != null)
				columnSelectPanel.removeAll();

			columnSelectPanel.setLayout(new BoxLayout(columnSelectPanel, BoxLayout.LINE_AXIS));
			columnSelectPanel.setBackground(Color.white);
			JPanel subP = new JPanel();
			subP.setBackground(Color.white);
			subP.setLayout(new BoxLayout(subP, BoxLayout.LINE_AXIS));
			subP.add(generalPanel);
			subP.add(libAndSetPanel);
			subP.setMaximumSize(subP.getPreferredSize());
			subP.setAlignmentX(CENTER_ALIGNMENT);
			
			if (librarySetNames != null && librarySetNames.length > 30)
			{
				JScrollPane sp = new JScrollPane(subP);
				columnSelectPanel.add(sp);
			}
			else
			{
				columnSelectPanel.add(subP);
			}
			columnSelectPanel.setMaximumSize(columnSelectPanel.getPreferredSize());
			columnSelectPanel.setAlignmentX(CENTER_ALIGNMENT);

 		}
 		private JPanel createPanel(boolean xAxis) {
 			JPanel retVal = new JPanel();
 			
 			retVal.setBackground(BGCOLOR);
 			retVal.setAlignmentX(Component.LEFT_ALIGNMENT);
 			
 			if(xAxis) retVal.setLayout(new BoxLayout(retVal, BoxLayout.LINE_AXIS));
 			else retVal.setLayout(new BoxLayout(retVal, BoxLayout.PAGE_AXIS));
 			
 			return retVal;
 		}
 		public String [] getAllColumnNames() {
 			String [] retVal = null;
 			
 			int totalColumns = generalColumnLabels.length + 
 					(lSetColumnLabels==null?0:lSetColumnLabels.length) + 
 					(uSetColumnLabels==null?0:uSetColumnLabels.length);
 			retVal = new String[totalColumns];
 			int index = 0;
 			
 			for(int x=0; x<generalColumnLabels.length; x++)
 				retVal[index++] = generalColumnLabels[x].getText();
 			if(lSetColumnLabels != null)
 				for(int x=0; x<lSetColumnLabels.length; x++)
 					retVal[index++] = lSetColumnLabels[x].getText();
 			if(uSetColumnLabels != null)
 				for(int x=0; x<uSetColumnLabels.length; x++)
 					retVal[index++] = uSetColumnLabels[x].getText();
 			
 			return retVal;
 		}
 		
 		public boolean [] getAllColumnSelections() {
 			boolean [] retVal = null;
 			
 			int totalColumns = generalColumnLabels.length + 
 					(lSetColumnLabels==null?0:lSetColumnLabels.length) + 
 					(uSetColumnLabels==null?0:uSetColumnLabels.length);
 			retVal = new boolean[totalColumns];
 			int index = 0;
 			
 			for(int x=0; x<generalColumnLabels.length; x++)
 				retVal[index++] = generalColumnLabels[x].isSelected();
 			if(lSetColumnLabels != null)
 				for(int x=0; x<lSetColumnLabels.length; x++)
 					retVal[index++] = lSetColumnLabels[x].isSelected();
 			if(uSetColumnLabels != null)
 				for(int x=0; x<uSetColumnLabels.length; x++)
 					retVal[index++] = uSetColumnLabels[x].isSelected();
 			
 			return retVal;
 		}
 		
 		public void setColumnSelections(String [] colNames) {
 			if(colNames == null) return;
 			Vector<String> selCols = new Vector<String> ();
 			for(int x=0; x<colNames.length; x++)
 				selCols.add(colNames[x]);
 			
 			for(int x=0; x<generalColumnLabels.length; x++)
 				generalColumnLabels[x].setSelected(selCols.contains(generalColumnLabels[x].getText()));
 			if(lSetColumnLabels != null)
	 			for(int x=0; x<lSetColumnLabels.length; x++)
	 				lSetColumnLabels[x].setSelected(selCols.contains(lSetColumnLabels[x].getText()));
 			if(uSetColumnLabels != null)
	 			for(int x=0; x<uSetColumnLabels.length; x++)
	 				uSetColumnLabels[x].setSelected(selCols.contains(uSetColumnLabels[x].getText()));
 		}
 		
 		public String [] getColumnSelections() {
 			Vector<String> selCols = new Vector<String> ();
 			
 			for(int x=0; x<generalColumnLabels.length; x++)
 				if(generalColumnLabels[x].isSelected())
 					selCols.add(generalColumnLabels[x].getText());
 			if(lSetColumnLabels != null)
 				for(int x=0; x<lSetColumnLabels.length; x++)
 					if(lSetColumnLabels[x].isSelected())
 						selCols.add(lSetColumnLabels[x].getText());
 			if(uSetColumnLabels != null)
	 			for(int x=0; x<uSetColumnLabels.length; x++)
	 				if(uSetColumnLabels[x].isSelected())
	 					selCols.add(uSetColumnLabels[x].getText());
 			
 			return selCols.toArray(new String[0]);
 		}
 		
		public void setOKListener(ActionListener l) { btnOK.addActionListener(l); }
		public void setCancelListener(ActionListener l) { btnCancel.addActionListener(l); }		
				
		private void saveSelections() {
			generalSelectionBuffer = new boolean[generalColumnLabels.length];
			for(int x=0; x<generalSelectionBuffer.length; x++)
				generalSelectionBuffer[x] = generalColumnLabels[x].isSelected();
			if(lSetColumnLabels==null)
				lSetSelectionBuffer = null;
			else {
				lSetSelectionBuffer = new boolean[lSetColumnLabels.length];
				for(int x=0; x<lSetSelectionBuffer.length; x++)
					lSetSelectionBuffer[x] = lSetColumnLabels[x].isSelected();
			}
			if(uSetColumnLabels==null)
				uSetSelectionBuffer = null;
			else {
				uSetSelectionBuffer = new boolean[uSetColumnLabels.length];
				for(int x=0; x<uSetSelectionBuffer.length; x++)
					uSetSelectionBuffer[x] = uSetColumnLabels[x].isSelected();
			}
		}
		
		private void restoreSelections() {
			if(generalSelectionBuffer != null)
				for(int x=0; x<generalSelectionBuffer.length; x++)
					generalColumnLabels[x].setSelected(generalSelectionBuffer[x]);
			if(lSetSelectionBuffer != null)
				for(int x=0; x<lSetSelectionBuffer.length; x++)
					lSetColumnLabels[x].setSelected(lSetSelectionBuffer[x]);
			if(uSetSelectionBuffer != null)
				for(int x=0; x<uSetSelectionBuffer.length; x++)
					uSetColumnLabels[x].setSelected(uSetSelectionBuffer[x]);
		}

		private JPanel generalPanel = null;
		private JPanel libAndSetPanel = null;
		private JPanel columnSelectPanel = null;
		private JButton btnOK = null, btnCancel = null;
		private JCheckBox [] generalColumnLabels = null;
		private JCheckBox [] lSetColumnLabels = null;
		private JCheckBox [] uSetColumnLabels = null;
		private boolean [] generalSelectionBuffer = null;
		private boolean [] lSetSelectionBuffer = null;
		private boolean [] uSetSelectionBuffer = null;
	}
	
	private class QueryModePanel extends JPanel {
		private static final long serialVersionUID = -7875669743302821252L;
		public QueryModePanel(String [] labels, int initSelect)
		{
			super.setBackground(BGCOLOR);
			setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
			setAlignmentX(Component.LEFT_ALIGNMENT);
			btnOptions = new JRadioButton[labels.length];
			modeGroup = new ButtonGroup();
			for(int x=0; x<labels.length; x++)
			{
				btnOptions[x] = new JRadioButton(labels[x]);
				btnOptions[x].addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						updateGroupSelection();
						updateViewMode();
						theParentTab.update();
					}
				});
				btnOptions[x].setBackground(Color.WHITE);
				add(btnOptions[x]);
				modeGroup.add(btnOptions[x]);				
			}
			btnOptions[initSelect].setSelected(true);
			setMaximumSize(getPreferredSize());
		} 
				
		public void setListener(ActionListener l)
		{
			for(int x=0; x<btnOptions.length; x++)
				btnOptions[x].addActionListener(l);
		}
		
		private void updateGroupSelection() {
			switch(getSelectedQueryMode()) {
			case QUERY_MODE_HIT_ID:				theSetViewPanel.setGroupMode(SetViewPanel.GROUP_MODE_USER_SELECT);
												break;
			case QUERY_MODE_HIT_DESCRIPTION:	theSetViewPanel.setGroupMode(SetViewPanel.GROUP_MODE_USER_SELECT);
												break;
			case QUERY_MODE_CONTIG_NAME:		theSetViewPanel.setGroupMode(SetViewPanel.GROUP_MODE_GROUP_ONLY);
												break;
			case QUERY_MODE_CONTIG_NOTE:		theSetViewPanel.setGroupMode(SetViewPanel.GROUP_MODE_GROUP_ONLY);
												break;
			case QUERY_MODE_CONTIG_READ:		theSetViewPanel.setGroupMode(SetViewPanel.GROUP_MODE_INDIVIDUAL_ONLY);
			}
		}
		
		public int getSelectedQueryMode() {
			String label = getSelectedLabel();
			if(label.equals(QUERY_MODE_HIT_ID_LABEL)) return QUERY_MODE_HIT_ID;
			if(label.equals(QUERY_MODE_HIT_DESCRIPTION_LABEL)) return QUERY_MODE_HIT_DESCRIPTION;
			if(label.equals(QUERY_MODE_CONTIG_NAME_LABEL)) return QUERY_MODE_CONTIG_NAME;
			if(label.equals(QUERY_MODE_CONTIG_NOTE_LABEL)) return QUERY_MODE_CONTIG_NOTE;
			if(label.equals(QUERY_MODE_CONTIG_READ_LABEL)) return QUERY_MODE_CONTIG_READ;
			return -1;
		}
		
		private String getSelectedLabel() {
			for(int x=0; x<btnOptions.length; x++)
				if(btnOptions[x].isSelected())
					return btnOptions[x].getText();
			return null;
		}
		
		private JRadioButton [] btnOptions = null;
		private ButtonGroup modeGroup = null;
	}
	
	private class SearchPanel extends JPanel {
		private static final long serialVersionUID = -5987399873828589062L;

		public SearchPanel(int type) {
			setType(type);
			setBackground(BGCOLOR);
			setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
			setAlignmentX(Component.LEFT_ALIGNMENT);
			
			lblHeader = new JLabel("Search");
			Dimension dim = lblHeader.getPreferredSize();
			dim.width = MAIN_PANEL_LABEL_WIDTH;
			lblHeader.setPreferredSize(dim);
			lblHeader.setMaximumSize(lblHeader.getPreferredSize());
			
			lblSearchHeader = new JLabel("Substring: ");
			
			txtField  = new JTextField(DEFAULT_PROMPT_SIZE);
			txtField.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
//					btnAddList.doClick();
//					updateExportButton();
				}
			});
			
			txtField.setMaximumSize(txtField.getPreferredSize());
			
			add(lblHeader);
			add(theModePanel);
			add(Box.createHorizontalStrut(10));
			add(lblSearchHeader);
			add(txtField);
		}
		
		public void addListener(ActionListener l) { theModePanel.setListener(l);}
		
		public int getQueryMode() { return theModePanel.getSelectedQueryMode(); }

		public void setType(int type) {
			if(type == BasicQueryTab.VIEW_BY_HIT) theModePanel = new QueryModePanel(HIT_QUERY_MODES, 1);
			else if(type == BasicQueryTab.VIEW_BY_SEQ) theModePanel = new QueryModePanel(CONTIG_QUERY_MODES, 0);
		}
		
		public String getSearchString() { return txtField.getText().trim(); }
		
		private JLabel lblHeader = null;
		private JLabel lblSearchHeader = null;
		private QueryModePanel theModePanel = null;
		private JTextField txtField = null;
	}
	
	private class SetViewPanel extends JPanel {
		private static final long serialVersionUID = 1536812149812674080L;
		public static final int GROUP_MODE_USER_SELECT = 0;
		public static final int GROUP_MODE_GROUP_ONLY = 1;
		public static final int GROUP_MODE_INDIVIDUAL_ONLY = 2;

		public SetViewPanel() {
			setBackground(BGCOLOR);
			setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
			setAlignmentX(Component.LEFT_ALIGNMENT);
			lblHeader = new JLabel("Alter table");
			Dimension dim = lblHeader.getPreferredSize();
			dim.width = MAIN_PANEL_LABEL_WIDTH;
			lblHeader.setPreferredSize(dim);
			lblHeader.setMaximumSize(lblHeader.getPreferredSize());
			add(lblHeader);
			
			btnSetColumns = new JButton("Select Columns");
			
			btnSetColumns.setBackground(ManagerFrame.MENUCOLOR);
			add(btnSetColumns);
			if(theParentTab.getType() == BasicQueryTab.VIEW_BY_HIT)
				showGrouped = new JCheckBox("Group by Hit ID", true);
			else if(theParentTab.getType() == BasicQueryTab.VIEW_BY_SEQ) {
				showGrouped = new JCheckBox("Group results", true);
				showGrouped.setVisible(false);
			}
				
			add(Box.createHorizontalStrut(10));
			add(showGrouped);
			setMaximumSize(getPreferredSize());
		}
		
		public void setGroupMode(int mode) {
			if(mode == nMode) return;
			
			if(nMode == GROUP_MODE_USER_SELECT) {
				saveState();
				showGrouped.setEnabled(false);
			} else if(mode == GROUP_MODE_USER_SELECT) {
				loadState();
				showGrouped.setEnabled(true);
			}
			nMode = mode;
			if(nMode == GROUP_MODE_GROUP_ONLY)
				showGrouped.setSelected(true);
			else if(nMode == GROUP_MODE_INDIVIDUAL_ONLY) 
				showGrouped.setSelected(false);
		}
		
		public boolean isGroupSelected() { return showGrouped.isSelected(); }
		
		public void addActionListenerForColumnSelect(ActionListener l) { btnSetColumns.addActionListener(l); }
		public void addActionListenerForGroupSelect(ActionListener l) { showGrouped.addActionListener(l); }
		
		private void saveState() { prevState = showGrouped.isSelected(); }
		private boolean loadState() { return prevState; }
		
		private JLabel lblHeader = null;
		private JButton btnSetColumns = null;
		private JCheckBox showGrouped = null;
		private int nMode = GROUP_MODE_USER_SELECT;
		private boolean prevState = false;
	}
	
	private class FilterPanel extends JPanel {
		private static final long serialVersionUID = -1687605347595522951L;

		public FilterPanel() {
			setBackground(BGCOLOR);
			setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
			setAlignmentX(Component.LEFT_ALIGNMENT);
			
			if(theParentTab.getType() == BasicQueryTab.VIEW_BY_HIT) {
				lblHeader = new JLabel("Filter");
				Dimension dim = lblHeader.getPreferredSize();
				dim.width = MAIN_PANEL_LABEL_WIDTH;
				lblHeader.setPreferredSize(dim);
				lblHeader.setMaximumSize(lblHeader.getPreferredSize());

				btnAnnoDBs = new JButton("AnnoDBs");
				btnAnnoDBs.setBackground(ManagerFrame.MENUCOLOR);
				btnSpecies = new JButton("Species");
				btnSpecies.setBackground(ManagerFrame.MENUCOLOR);
				btnAttributes = new JButton("Attributes");
				btnAttributes.setBackground(ManagerFrame.MENUCOLOR);

				add(lblHeader);				
				add(btnAnnoDBs);
				add(Box.createHorizontalStrut(5));
				add(btnSpecies);
				add(Box.createHorizontalStrut(5));
				add(btnAttributes);
			}			
		}
		
		public void addActionListenerForAnnoDBSelect(ActionListener l) { if(btnAnnoDBs != null) btnAnnoDBs.addActionListener(l); }
		public void addActionListenerForSpeciesSelect(ActionListener l) { if(btnSpecies != null) btnSpecies.addActionListener(l); }
		public void addActionListenerForAttributeSelect(ActionListener l) { if(btnAttributes != null) btnAttributes.addActionListener(l); }
		
		private JLabel lblHeader = null;
		private JButton btnAnnoDBs = null;
		private JButton btnSpecies = null;
		private JButton btnAttributes = null;
	}
	
	private class ResultsPanel extends JPanel {
		private static final long serialVersionUID = 7170075510204650723L;

		public ResultsPanel() {
			setBackground(BGCOLOR);
			setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
			setAlignmentX(Component.LEFT_ALIGNMENT);
			
				lblHeader = new JLabel("Results");
				Dimension dim = lblHeader.getPreferredSize();
				dim.width = MAIN_PANEL_LABEL_WIDTH;
				lblHeader.setPreferredSize(dim);
				lblHeader.setMaximumSize(lblHeader.getPreferredSize());
				
				btnAddList = new JButton("ADD TO TABLE");
				btnAddList.setBackground(ManagerFrame.FUNCTIONCOLOR);
	
				btnAddList.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						theParentTab.addListFromQuery();
					}
				});
				
				txtLimit = new JTextField(10);
				txtLimit.setText(Integer.toString(DEFAULT_RESULT_LIMIT));
				txtLimit.setMaximumSize(txtLimit.getPreferredSize());

				lblLimit = new JLabel("Limit: ");
				
				add(lblHeader);
				add(btnAddList);
				add(Box.createHorizontalStrut(10));
				add(lblLimit);
				add(txtLimit);
		}
		
		public void setAddToTableEnabled(boolean enabled) { btnAddList.setEnabled(enabled); }

		public int getLimit() {
			if(txtLimit.getText().matches("[0-9]+"))
				return Integer.parseInt(txtLimit.getText());
				
			System.out.println("Invalid limit '" + txtLimit.getText() + "', using default: " + DEFAULT_RESULT_LIMIT);
			txtLimit.setText(Integer.toString(DEFAULT_RESULT_LIMIT));
			return DEFAULT_RESULT_LIMIT;
		}
		
		private JLabel lblHeader = null, lblLimit = null;
		private JButton btnAddList = null;
		private JTextField txtLimit = null;
	}
	
	private String [] strIndividualHitColumnSelections = null;
	private String [] strIndividualContigColumnSelections = null;
	private String [] strGroupHitColumnSelections = null;
	private String [] strGroupContigColumnSelections = null;
	
	private String [] indContigGeneralColumnLabels = null;
	private String [] grpContigGeneralColumnLabels = null;
	private String [] indHitGeneralColumnLabels = null;
	private String [] grpHitGeneralColumnLabels = null;
	
	private String [] lSetNames = null;
	private String [] uSetNames = null;

	private int nViewMode = -1;
	
	private SetViewPanel theSetViewPanel = null;
	private SearchPanel theSearchPanel = null;
	private FilterPanel theFilterPanel = null;
	private ResultsPanel theResultsPanel = null;
	
	private ColumnSelectionPanel columnDataPanel = null;
	private AnnoSelectionPanel annoDBPanel = null;
	private SpeciesSelectionPanel speciesPanel = null;
	private AttributePanel attributePanel = null;
	private BasicQueryTab theParentTab = null;
}
